#include "SocketIO.h"
#include <unistd.h>
#include <sys/socket.h>

SocketIO::SocketIO(int fd)
: _fd(fd)
{}

SocketIO::~SocketIO()
{}

size_t SocketIO::readn(char *buf, size_t len)
{
    size_t bytes_read = 0;
    while(bytes_read < len)    
    {
        ssize_t ret = ::read(_fd, buf + bytes_read, len - bytes_read);
        if(ret < 0)
        {
            if(errno == EINTR) continue; // 信号中断 重试
            throw std::system_error(errno, std::system_category(), "read failed.");
        }
        if(ret == 0) break;
        bytes_read += ret;
    }
    return bytes_read;
}

size_t SocketIO::writen(const char *buf, size_t len)
{
    size_t bytes_write = 0;
    while(bytes_write < len)
    {
        ssize_t ret = ::write(_fd, buf + bytes_write, len - bytes_write);
        if(ret < 0)
        {
            if(errno == EINTR) continue;
            throw std::system_error(errno, std::system_category(), "write failed.");
        }
        if(ret == 0) break;
        bytes_write += ret;
    }
    return bytes_write;
}

size_t SocketIO::readLine(char *buf, size_t maxlen)
{
    if(maxlen < 1) return 0;
    int ret = 0;

    size_t bytes_read = 0;
    size_t left = maxlen - 1;
    char *pstr = buf;
    while(0 < left)
    {
        // 不读出
        ret = ::recv(_fd, pstr, maxlen, MSG_PEEK);
        if(ret == -1 && errno == EINTR) continue;
        else if(ret == -1)
        {
            throw std::system_error(errno, std::system_category(), "recv failed.");
        }
        else if(ret == 0) break;
        else
        {
            for(int i = 0; i < ret; ++i)
            {
                if(pstr[i] == '\n') // 行末尾 
                {
                    int sz = i + 1;
                    readn(pstr, sz);
                    pstr += sz;
                    *pstr = '\0';
                    return bytes_read + sz;
                }
            }
        }
        readn(pstr, ret);
        pstr += ret;
        left -= ret;
        bytes_read += ret;
    }
    *pstr = '\0';
    return maxlen - left;
}